package com.guodi.model.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guodi.common.utils.ExcelUtil;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.secure.utils.AuthUtil;
import com.guodi.model.entity.*;
import com.guodi.model.mapper.IdtFillProblemMapper;
import com.guodi.model.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guodi.model.vo.ApiIdtProblemVo;
import com.guodi.model.vo.ApiProblemSceneIndicatorsVo;
import com.guodi.model.vo.ApiProblemToExcelVo;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
* 指标填报体检关联问题 服务实现类
* @author lzy
* @date 2023-05-31
*/
@Service
public class IdtFillProblemServiceImpl extends ServiceImpl<IdtFillProblemMapper, IdtFillProblem> implements IIdtFillProblemService {

    @Resource
    private IdtFillProblemMapper idtFillProblemMapper;

    @Resource
    public IDiagnosisProblemSceneService diagnosisProblemSceneService;
    @Resource
    private IIdtIndicatorsDirService iIdtIndicatorsDirService;
    @Resource
    private IIdtIndicatorsService iIdtIndicatorsService;



    @Override
    public void generateProblem(IdtFillTask task) {

        //查出所有的问题库数据
        List<DiagnosisProblemScene> problemScenes = diagnosisProblemSceneService.list();

        //查出所有的该任务的指标值
        Map<String, ApiIndicatorsVal> fillValueMap = iIdtIndicatorsDirService.idToMapVal(task.getYear(), task.getDivisionCode());

        List<IdtFillProblem> result = new ArrayList<>();
        for(DiagnosisProblemScene problemScene : problemScenes){

            boolean flag = this.triggerIssue(problemScene,fillValueMap);
            if(flag){
                IdtFillProblem problem = new IdtFillProblem();
                problem.setId(UuidUtil.get32UUID());
                problem.setYear(task.getYear());
                problem.setDivisionCode(task.getDivisionCode());
                problem.setProblemId(problemScene.getId());
                problem.setCreator(AuthUtil.getUserId().toString());
                problem.setCreateTime(new Date());
                result.add(problem);
            }
        }
        this.saveBatch(result);
    }

    /**
     * @描述: 问题触发器
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/5/31 16:00
     **/
    public boolean triggerIssue(DiagnosisProblemScene problemScene, Map<String,ApiIndicatorsVal> fillValueMap) {
        String ruleJson = problemScene.getRelatedIndicators();
        List<ApiProblemSceneIndicatorsVo> rules = JSONArray.parseArray(ruleJson, ApiProblemSceneIndicatorsVo.class);

        boolean ruleFlag = true;
        for(ApiProblemSceneIndicatorsVo rule : rules){
            ruleFlag = this.matchingRules(rule, fillValueMap);

            if(Objects.equals("and",problemScene.getIdtRule())){
                //如果是and并且单个规则未命中问题，则不触发,返回false
                if(!ruleFlag){
                    return ruleFlag;
                }
            }else {
                //如果是or并且单个规则命中问题，则触发,返回true
                if(ruleFlag){
                    return ruleFlag;
                }
            }
        }
        return ruleFlag;
    }

    /**
     * @描述: 匹配规则
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/5/31 16:10
     **/
    private boolean matchingRules(ApiProblemSceneIndicatorsVo rule, Map<String,ApiIndicatorsVal> fillValueMap){
        boolean flag = false;
        try {
            ApiIndicatorsVal apiIndicatorsVal = fillValueMap.get(rule.getIdtId());
            //没有该指标值，直接不满足问题库规则
            if(null == apiIndicatorsVal){
                return flag;
            }

            //获取对比对象的值
            Method mGet = apiIndicatorsVal.getClass().getMethod("get"+rule.getComparObject());
            String value = (String)mGet.invoke(apiIndicatorsVal);
            if(StringUtils.isEmpty(value)){
                return false;
            }

            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("js");

            //公式规则：监测值 + “符号” + “对比对象值”

            switch (rule.getSymbol()) {
                case "≤":
                    rule.setSymbol("<=");
                    break;
                case "≥":
                    rule.setSymbol(">=");
                    break;
            }
            String calculationFormula = apiIndicatorsVal.getMonitorValue() + rule.getSymbol()  + value;

            Object obectResult;
            if(Objects.equals("=",rule.getSymbol())){
                Double aDouble = Double.valueOf(apiIndicatorsVal.getMonitorValue());
                Double aDouble1 = Double.valueOf(value);
                if(aDouble.compareTo(aDouble1) == 0){
                    obectResult = true;
                }else {
                    obectResult = false;
                }
            }else {
                obectResult = engine.eval(calculationFormula);
            }

            if ((boolean) obectResult) {
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
            return flag;
        }
        return flag;
    }


    @Override
    public IPage<ApiProblemToExcelVo> pageDetail(Page page, String year, String divisionCode) {
        IPage<ApiProblemToExcelVo> iPage = this.idtFillProblemMapper.pageDetail(page,year,divisionCode);
        if(CollectionUtils.isEmpty(iPage.getRecords())){
            return iPage;
        }
        List<IdtIndicators> idtIndicatorList = iIdtIndicatorsService.list();
        Map<String, IdtIndicators> idtIdToMap = idtIndicatorList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e, (e1, e2) -> e2));

        List<ApiProblemToExcelVo> vos = iPage.getRecords();
        int i = 1;
        for(ApiProblemToExcelVo vo :vos){
            vo.setNum(i);
            String ruleJson = vo.getRelatedIndicators();
            List<ApiProblemSceneIndicatorsVo> rules = JSONArray.parseArray(ruleJson, ApiProblemSceneIndicatorsVo.class);

            StringBuffer buffer = new StringBuffer();
            for(ApiProblemSceneIndicatorsVo rule : rules){
                IdtIndicators idtIndicators = idtIdToMap.get(rule.getIdtId());
                if(null == idtIndicators){
                    continue;
                }
                buffer.append(idtIndicators.getName()).append("（").append(idtIndicators.getUnit()).append("）");
            }
            vo.setRelatedIndicators(buffer.toString());
            i++;
        }
        return iPage;
    }

    @Override
    public void downLoadFile(String year, String divisionCode, HttpServletResponse response) {
        List<ApiProblemToExcelVo> list = this.idtFillProblemMapper.problemList(year,divisionCode);

        List<IdtIndicators> idtIndicatorList = iIdtIndicatorsService.list();
        Map<String, IdtIndicators> idtIdToMap = idtIndicatorList.stream().collect(Collectors.toMap(e -> e.getId(), e -> e, (e1, e2) -> e2));

        int i = 1;
        for(ApiProblemToExcelVo vo : list){
            vo.setNum(i);
            String ruleJson = vo.getRelatedIndicators();
            List<ApiProblemSceneIndicatorsVo> rules = JSONArray.parseArray(ruleJson, ApiProblemSceneIndicatorsVo.class);

            StringBuffer buffer = new StringBuffer();
            for(ApiProblemSceneIndicatorsVo rule : rules){
                IdtIndicators idtIndicators = idtIdToMap.get(rule.getIdtId());
                if(null == idtIndicators){
                    continue;
                }
                buffer.append(idtIndicators.getName()).append("（").append(idtIndicators.getUnit()).append("）");
            }
            vo.setRelatedIndicators(buffer.toString());
            i++;
        }
        ExcelUtil.exportExcel(list, null, "城市体检疑似问题及建设改进策略", ApiProblemToExcelVo.class, "城市体检疑似问题及建设改进策略表.xls", response);

//        Workbook workbook = ExcelUtil.buildWorkbook(list, "城市体检疑似问题及建设改进策略", "城市体检疑似问题及建设改进策略", ApiProblemToExcelVo.class);
//        try {
//            String fileName = "城市体检疑似问题及建设改进策略表";
//            response.reset();
//            response.setContentType("application/octet-stream");
//            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + ".xlsx");
////            response.setHeader("Access-Control-Allow-Origin", "*");
//            response.setHeader("Access-Control-Allow-Methods", "GET,POST");
//            OutputStream outputStream = response.getOutputStream();
//            workbook.write(outputStream);
//            outputStream.flush();
//            outputStream.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    @Override
    public List<ApiIdtProblemVo> getProblemList(String year, String divisionCode) {
        return this.idtFillProblemMapper.getProblemList(year,divisionCode);
    }

    @Override
    public String getProblemNameById(String problemId) {
        String problemName = "";
        if(!StringUtils.isEmpty(problemId)){
            List<String> names = this.idtFillProblemMapper.getProblemNameById(Arrays.asList(problemId.split(";")));
            if(!CollectionUtils.isEmpty(names)){
                problemName = String.join("、",names);
            }
        }
        return problemName;
    }


}
